﻿using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Marbles.Core.Web
{
    public class GlobalVariable<T>
    {

        public T Value
        {
            get { return this.GetValue(); }
            set { this.SetValue(value); }
        }

        public GlobalVariableStore Store
        {
            get { return this._store; }
        }

        public string Name
        {
            get { return this.varname; }
        }

        private GlobalVariableStore _store = GlobalVariableStore.Session;
        private string varname = string.Empty;

        public GlobalVariable(string Name, T value, GlobalVariableStore Store)
        {
            this.varname = Name.Trim();
            this.Value = value;
            this._store = Store;
        }

        private void SetValue(T value)
        {
            switch (this._store)
            {
                case GlobalVariableStore.Application:
                    HttpContext.Current.Application[varname] = value;
                    break;
                case GlobalVariableStore.Cache:
                    if (HttpContext.Current.Cache[varname] == null)
                    {
                        HttpContext.Current.Cache.Add(varname, value, null, DateTime.Now.AddDays(1), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
                    }
                    else
                    {
                        HttpContext.Current.Cache[varname] = value;
                    }
                    break;
                case GlobalVariableStore.Cookie:
                    HttpCookie cookievalue = HttpContext.Current.Request.Cookies[varname];

                    if (cookievalue == null)
                    {
                        cookievalue = new HttpCookie(varname);
                    }                    
                    HttpContext.Current.Request.Cookies[varname].Value = Serialize(value);
                    break;
                case GlobalVariableStore.Session:
                    HttpContext.Current.Session[varname] = value;
                    break;
            }
        }

        private T GetValue()
        {
            object obj = default(T);

            switch (this._store)
            {
                case GlobalVariableStore.Application:
                    obj = HttpContext.Current.Application[varname];
                    break;
                case GlobalVariableStore.Cache:
                    obj = HttpContext.Current.Cache[varname];
                    break;
                case GlobalVariableStore.Cookie:
                    if (HttpContext.Current.Request.Cookies[varname] != null) { obj = Deserialize(HttpContext.Current.Request.Cookies[varname].Value); }
                    break;
                case GlobalVariableStore.Session:
                    obj = HttpContext.Current.Session[varname];
                    break;
            }

            if (obj == null) { obj = default(T); }
            return (T)obj;
        }

        public static bool operator ==(GlobalVariable<T> v1, GlobalVariable<T> v2)
        {
            return v1.Value.Equals(v2.Value);
        }

        public static bool operator !=(GlobalVariable<T> v1, GlobalVariable<T> v2)
        {
            return !v1.Value.Equals(v2.Value);
        }

        public override bool Equals(object obj)
        {
            return obj.Equals(this);
        }

        public override int GetHashCode()
        {
            return this.Value.GetHashCode();
        }

        public override string ToString()
        {
            return this.Value.ToString();
        }


        private string Serialize(object o)
        {
            LosFormatter ser = new LosFormatter();
            StringWriter sw = new StringWriter();
            ser.Serialize(sw, o);
            sw.Flush();
            return sw.ToString();
        }

        private object Deserialize(string value)
        {
            if (value == string.Empty) { return null; }
            LosFormatter ser = new LosFormatter();
            return ser.Deserialize(value);
        }
    }

    public enum GlobalVariableStore
    {
        Session, Cookie, Cache, Application
    }
}

